package OBJ;

import DataStructure.Face;
import DataStructure.Model;
import DataStructure.Normal;
import DataStructure.TextureCoordinate;
import org.joml.Vector3f;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

// OBJ模型加载器
public class ObjModelLoader {
    public static Model loadModel(String path,String name) throws IOException {
        // 创建模型对象
        Model model = new Model();
        Model.Material currentMaterial = null;
        // 顶点、纹理坐标、法线、面
        ArrayList<Vector3f> vertices = new ArrayList<>();
        ArrayList<TextureCoordinate> textureCoordinates = new ArrayList<>();
        ArrayList<Normal> normals = new ArrayList<>();
        ArrayList<Face> faces = new ArrayList<>();
        // 读取文件
        File file = new File(path+name+".obj");
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        while ((line = reader.readLine()) != null) {
            // 以空白字符分割
            String[] parts = line.split("\\s+");
            switch (parts[0]) {
                case "v":   // 顶点
                    vertices.add(new Vector3f( Float.parseFloat(parts[1]), Float.parseFloat(parts[2]), Float.parseFloat(parts[3])));
                    break;
                case "vt":  // 纹理坐标
                    textureCoordinates.add(new TextureCoordinate(Float.parseFloat(parts[1]), Float.parseFloat(parts[2])));
                    break;
                case "vn":  // 法线
                    normals.add(new Normal(Float.parseFloat(parts[1]), Float.parseFloat(parts[2]), Float.parseFloat(parts[3])));
                    break;
                case "f":   // 面
                    processFace(parts,faces, currentMaterial);
                    break;
                case "usemtl":  // 使用材质
                        String mtlName = line.substring(7).trim();
                        currentMaterial = model.materials.stream()
                                .filter(m -> m.name.equals(mtlName))
                                .findFirst()
                                .orElseGet(() -> {                                  // 若不存在则创建新材质
                                    Model.Material m = new Model.Material();
                                    m.name = mtlName;
                                    model.materials.add(m);
                                    return m;                                       // 返回新材质
                                });
                    break;

            }
        }
        reader.close();


        model.set(vertices, textureCoordinates, normals, faces);
        return model;
    }
    public static void  loadMtl(String path,String name,Model model) throws IOException {
        File mtlFile = new File(path+name+".mtl");
        BufferedReader mtlReader = new BufferedReader(new FileReader(mtlFile));
        String mtlLine;
        String currentMaterialName = null;
        while ((mtlLine = mtlReader.readLine()) != null) {
            String[] parts = mtlLine.split("\\s+");
            switch (parts[0]) {
                case "newmtl" ->{
                    currentMaterialName = parts[1];
                }
                case "map_Kd" ->{
                    for(Model.Material m : model.materials){
                        if(Objects.equals(m.name, currentMaterialName)){
                            m.path =path+parts[1];
                            m.loadTexture();

                        }
                    }
                }
            }

        }
    }
    // 处理面数据, 三角化处理
    private static void processFace(String[] parts,
                                    List<Face> faces,
                                    Model.Material currentMaterial) {
        // 跳过第一个元素（"f"标识）
        String[] faceVertices = Arrays.copyOfRange(parts, 1, parts.length);

        // 三角化处理
        if (faceVertices.length < 3) return; // 无效面
        if (faceVertices.length == 3) {
            // 已经是三角形，直接添加
            addFace(faces, faceVertices[0], faceVertices[1], faceVertices[2], currentMaterial);
        } else {
            // 多边形面，进行三角化（使用扇形分割法）
            for (int i = 1; i < faceVertices.length - 1; i++) {
                addFace(faces, faceVertices[0], faceVertices[i], faceVertices[i + 1], currentMaterial);
            }
        }
    }

    private static void addFace(List<Face> faces, String v1, String v2, String v3, Model.Material material) {
        Face face = new Face();
        processVertex(v1, face);//第一个顶点
        processVertex(v2, face);//第二个顶点
        processVertex(v3, face);//第三个顶点
        face.material = material;
        faces.add(face);
        if (material != null) material.faces.add(face);
    }

    private static void processVertex(String vertexData, Face face) {
        String[] indices = vertexData.split("/");
        int vertexIndex = parseIndex(indices[0], 1); // 顶点索引
        int texIndex = indices.length > 1 ? parseIndex(indices[1], 2) : -1;
        int normalIndex = indices.length > 2 ? parseIndex(indices[2], 3) : -1;

        face.addVertexIndices(vertexIndex);
        if (texIndex != -1) face.addTextureCoordinateIndices(texIndex);
        if (normalIndex != -1) face.addNormalIndices(normalIndex);
    }

    private static int parseIndex(String str, int component) {
        if (str == null || str.isEmpty()) return -1;
        int index = Integer.parseInt(str);
        return index > 0 ? index - 1 : index; // 处理负索引（相对索引）
    }
}